package pl.wr.physics.operations;

import pl.wr.math.number.Fraction;
import pl.wr.physics.units.AbstractUnit;
import pl.wr.physics.units.SI.base.A;
import pl.wr.physics.units.SI.base.kg;
import pl.wr.physics.units.SI.base.m;
import pl.wr.physics.units.SI.derived.multidim.m2;
import pl.wr.physics.units.SI.derived.multidim.m3;

/**
 * @version 1.0
 * @author wieslaw.rodak
 */
public class Processor {

	/**
	 * Method add.
	 * 
	 * @param x
	 *            AbstractUnit
	 * @param y
	 *            AbstractUnit
	 * @return AbstractUnit
	 */
	public static AbstractUnit add(AbstractUnit x, AbstractUnit y) {

		if (x.getClass().isInstance(y)) {
			final Fraction number = Fraction.add(x.getValue(), y.getValue());

			return returnInstance(x, number);
		}
		throw new IllegalArgumentException(prepereExceptionMessage(x, y));
	}

	/**
	 * Method multi.
	 * 
	 * @param x
	 *            AbstractUnit
	 * @param y
	 *            AbstractUnit
	 * @return AbstractUnit
	 */
	public static AbstractUnit multi(AbstractUnit x, AbstractUnit y) {

		if (x.getClass().isInstance(y) && x instanceof m) {
			final Fraction number = Fraction.multiply(x.getValue(),
					y.getValue());
			return new m2(number);
		}
		throw new IllegalArgumentException(prepereExceptionMessage(x, y));
	}

	/**
	 * Method multi.
	 * 
	 * @param x
	 *            AbstractUnit
	 * @param y
	 *            AbstractUnit
	 * @param z
	 *            AbstractUnit
	 * @return AbstractUnit
	 */
	public static AbstractUnit multi(AbstractUnit x, AbstractUnit y,
			AbstractUnit z) {

		if (x instanceof m && y instanceof m && z instanceof m) {
			final Fraction number = Fraction
					.multiply(Fraction.multiply(x.getValue(), y.getValue()),
							z.getValue());
			return new m3(number);
		}
		throw new IllegalArgumentException(prepereExceptionMessage(x, y, z));
	}

	/**
	 * Method returnInstance.
	 * 
	 * @param unit
	 *            AbstractUnit
	 * @param value
	 *            Fraction
	 * @return AbstractUnit
	 */
	public static AbstractUnit returnInstance(AbstractUnit unit, Fraction value) {
		if (unit instanceof A) {
			return new A(value);
		} else if (unit instanceof kg) {
			return new kg(value);
		} else if (unit instanceof m) {
			return new m(value);
		}

		throw new IllegalArgumentException(prepereExceptionMessage(unit));
	}

	/**
	 * @param list
	 *            of Unit Objects
	 * @return String message
	 */
	private static String prepereExceptionMessage(AbstractUnit... list) {
		StringBuffer sb = new StringBuffer();
		sb.append("Instance of [ ");
		for (AbstractUnit abstractUnit : list) {
			sb.append(abstractUnit.getClass().getSimpleName());
			sb.append(' ');
		}
		sb.append("] is not defined as legal argument!");
		return sb.toString();
	}

}
